﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;
using Entity.Package;
using System.Configuration;
using System.Threading;
using BLL.Business;
using Tools;

namespace BLL.CSocket
{
    public class ClientThread
    {
      
        private Socket _client;
        byte[] buffer = new byte[2048];

        private static Socket socketServer;
        public static bool IsRun=true;

        public ClientThread(Socket clientSocket)
        {
            this._client = clientSocket;
            _client.ReceiveTimeout = 50000;
            _client.ReceiveBufferSize = 2048;  //最大缓存
            _client.NoDelay = true;
          
        }
      
        /// <summary>
        /// 发送数据包
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="sendMsg"></param>
        /// <returns></returns>
        public bool Send(byte[] buffer)
        {
            if (_client.Connected == false)
                return false;

            if (buffer == null)
            {
                PackFailReturn pkFailReturn = new PackFailReturn();
                pkFailReturn.TradeCode = ((int)TradeCode.网络错误).ToString();
                pkFailReturn.ResponseCode = ((int)ResponseCode.数据包格式错).ToString().PadLeft(3,'0');
                pkFailReturn.PackHead = new PackHead("00", "00000000000000", (Encoding.Default.GetBytes(pkFailReturn.ToString()).Length).ToString());
                CSocket.PackageHandle.SendFailurPackage(pkFailReturn,this);

                LogHelper.WriteInfoLog("发送内容为空响应包");
                return false;
            }

            _client.SendTimeout = 60000;
            try
            {
                int sendCount = 0;
                while (sendCount < buffer.Length)
                {
                    sendCount += _client.Send(buffer);                   
                }
                
                return true;
            }
            catch(Exception ex)
            {
                LogHelper.WriteErrorLog(string.Format("Send方法-发送数据包出现异常，异常信息：{0}", ex.Message),ex);
                CloseSocket();
                return false;
            }
        }

        /// <summary>
        /// 接收数据包
        /// </summary>
        /// <param name="socket"></param>
        /// <param name="pkgType"></param>
        /// <returns></returns>
        public void Receive()
        {
            if (_client.Connected == false)
                return;
            
            bool keepAlive = true;
            PackFailReturn pkFailReturn = new PackFailReturn();
            pkFailReturn.TradeCode = ((int)TradeCode.网络错误).ToString();
            pkFailReturn.ResponseCode = ((int)ResponseCode.其他错误).ToString().PadLeft(3,'0');
            pkFailReturn.PackHead = new PackHead("00", "00000000000000", (Encoding.Default.GetBytes(pkFailReturn.ToString()).Length).ToString());

            while (keepAlive)
            {
                if (!IsRun)
                {
                    CSocket.PackageHandle.SendFailurPackage(pkFailReturn, this);
                    CloseSocket();
                    LogHelper.WriteInfoLog("服务要停止，中止接收数据");
                    break;
                }

                try
                {
                    int packLen= _client.Receive(buffer);
                    if (packLen>0 && PackageHandle.UnfoldingPackage(buffer,this))  //包已收完，退出循环
                        keepAlive = false;
                }
                catch (Exception ex)   //出现任何异常，客户端Socket关闭
                {
                    CSocket.PackageHandle.SendFailurPackage(pkFailReturn, this);
                    keepAlive = false;
                    LogHelper.WriteErrorLog("Receive方法-接收数据包出现异常，异常信息：" + ex.Message, ex);
                }                
            }
        }

        public void CloseSocket()
        {
            try
            {
                if (_client.Connected == true)
                {
                    _client.Shutdown(SocketShutdown.Both);
                    _client.Close();
                    Business.Common.ThreadCount -= 1;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorLog("CloseSocket方法-关闭链接异常：" + ex.Message, ex);
            }
        }

        public static void StartServer()
        {
            try
            {
                socketServer = null; //服务器端的套接字，用于监听客户端连接
                int port = int.Parse(ConfigurationManager.AppSettings["PortNumber"].ToString());
                int maxThreadCount = int.Parse(ConfigurationManager.AppSettings["MaxThreadNumber"].ToString()); //最大线程数

                socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                socketServer.NoDelay = true;
                IPAddress ip = IPAddress.Parse(ConfigurationManager.AppSettings["IpAddress"].ToString());
                EndPoint ep = new IPEndPoint(ip, port);
                socketServer.Bind(ep);
                socketServer.Listen(20);   //置于侦听状态
              
                while (IsRun)
                {
                    Socket client = socketServer.Accept();
                    ClientThread newclient = new ClientThread(client);
                    Thread thread = new Thread(new ThreadStart(newclient.Receive));

                    if (BLL.Business.Common.ThreadCount < maxThreadCount)
                    {
                        thread.Start();
                    }
                }

                socketServer.Shutdown(SocketShutdown.Both);
                socketServer.Close();
            }
            catch (Exception ex)
            {
                socketServer.Shutdown(SocketShutdown.Both);
                socketServer.Close();
                LogHelper.WriteErrorLog("StartServer方法-程序入口异常：" + ex.Message, ex);
            }
        }
    }
}
